package com.feng.timu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feng.common.consts.QuAnswerConstant;
import com.feng.common.consts.QuTypeConstant;
import com.feng.common.dto.PageDto;
import com.feng.common.enums.ApiErrorEnum;
import com.feng.common.enums.QuTypeEnum;
import com.feng.common.exceptions.ServiceException;
import com.feng.common.vo.ApiRest;
import com.feng.common.vo.PageResult;
import com.feng.tiku.entity.Repo;
import com.feng.tiku.mapper.RepoMapper;
import com.feng.timu.dto.QuDto;
import com.feng.timu.dto.QuPagingDto;
import com.feng.timu.entity.Qu;
import com.feng.timu.entity.QuAnswer;
import com.feng.timu.entity.QuRepo;
import com.feng.timu.mapper.QuAnswerMapper;
import com.feng.timu.mapper.QuMapper;
import com.feng.timu.mapper.QuRepoMapper;
import com.feng.timu.service.QuService;
import com.feng.timu.vo.QuVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 问题题目 服务实现类
 * </p>
 *
 * @author feng
 * @since 2023-03-21 15:34:38
 */
@Service
public class QuServiceImpl extends ServiceImpl<QuMapper, Qu> implements QuService {

    @Autowired
    private QuAnswerMapper quAnswerMapper;

    @Autowired
    private QuRepoMapper quRepoMapper;

    @Autowired
    private RepoMapper repoMapper;

    @Override
    @Transactional
    public ApiRest insertQu(QuDto quDto) {
        checkData(quDto);
        //插入题目
        Qu qu = new Qu();
        BeanUtil.copyProperties(quDto, qu);
        qu.setUpdateTime(new Date());
        int count = baseMapper.insert(qu);
        updateCount(count, "题目插入异常", 0);
        //正确答案插入
        List<QuAnswer> quAnswerList = quDto.getQuAnswerList();
        int quAnswerCount = 0;
        for (QuAnswer quAnswer : quAnswerList) {
            quAnswer.setQuId(qu.getId());
            quAnswerMapper.insert(quAnswer);
            quAnswerCount++;
        }
        updateCount(quAnswerCount, "答案插入异常", quAnswerList.size());
        //维护qu,repo中间表,更新repo表
        Integer quType = qu.getQuType();
        int quRepoCount = 0;
        //存储的quRepoId
        List<String> quRepoList = quDto.getQuRepoList();
        for (String id : quRepoList) {
            // 在循环里new，让quRepo对象的id重置
            QuRepo quRepo = new QuRepo();
            //维护qu,repo中间表
            quRepo.setQuId(qu.getId());
            quRepo.setRepoId(id);
            quRepo.setQuType(quType);
            quRepoMapper.insert(quRepo);
            quRepoCount++;
            //更新repo表
            UpdateRepo(quType, quRepo);
        }
        updateCount(quRepoCount, "题库插入异常", quRepoList.size());
        return ApiRest.success("题目添加成功", null);
    }

    @Override
    @Transactional
    public ApiRest updateQu(QuDto quDto) {
        checkData(quDto);
        //跟新 题目
        Qu qu = new Qu();
        BeanUtil.copyProperties(quDto, qu);
        qu.setUpdateTime(new Date());
        baseMapper.updateById(qu);
        //跟新 答案
        List<QuAnswer> quAnswerList = quDto.getQuAnswerList();
        for (QuAnswer quAnswer : quAnswerList) {
            quAnswerMapper.updateById(quAnswer);
        }
        //更新 题库
        Integer quType = qu.getQuType();
        List<String> quRepoList = quDto.getQuRepoList();
        if (quRepoList.size() == 0) {
            throw new ServiceException(ApiErrorEnum.QU_REPO_ATLEAST_ONE);
        }
        QueryWrapper<QuRepo> queryWrapper = new QueryWrapper<>();
        for (String id : quRepoList) {
            queryWrapper.lambda()
                    .eq(QuRepo::getQuId, qu.getId())
                    .eq(QuRepo::getRepoId, id);
            QuRepo quRepo = quRepoMapper.selectOne(queryWrapper);
            if (quRepo == null) {
                quRepo = new QuRepo();
                quRepo.setQuId(qu.getId());
                quRepo.setRepoId(id);
                quRepo.setQuType(quType);
                quRepoMapper.insert(quRepo);
            } else {
                quRepo.setQuType(quType);
                quRepoMapper.updateById(quRepo);
            }
            //更新repo表
            UpdateRepo(quType, quRepo);

        }
        return ApiRest.success("修改成功", null);
    }

    private void UpdateRepo(Integer quType, QuRepo quRepo) {
        Repo repo = repoMapper.selectById(quRepo.getRepoId());
        switch (QuTypeEnum.getByType(quType)) {
            case RADIO:
                repo.setRadioCount(repo.getRadioCount() + 1);
                break;
            case MULTI:
                repo.setMultiCount(repo.getMultiCount() + 1);
                break;
            case JUDGE:
                repo.setJudgeCount(repo.getJudgeCount() + 1);
                break;
            case JDT:
                repo.setJdtCount(repo.getJdtCount() + 1);
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + quType);
        }
        repoMapper.updateById(repo);
    }

    @Override
    public PageResult<Qu> pagingQu(PageDto<QuPagingDto> pageDto) {
        if (pageDto == null) {
            throw new ServiceException("分页参数异常");
        }
        Integer nowPage = Opt.ofBlankAble(pageDto.getNow()).orElse(1);
        Integer size = Opt.ofBlankAble(pageDto.getSize()).orElse(5);
        Page<Qu> page = new Page<>(nowPage, size);
        List<Qu> quList = baseMapper.pagingQu(page, pageDto.getWhere());
        return new PageResult<>(page.getTotal(), quList, page.getPages());
    }

    @Override
    public ApiRest<QuVO> findQu(String quId) {
        QuVO qu = baseMapper.findQu(quId);
        return ApiRest.success("查询成功", qu);
    }


    private void updateCount(int count, String msg, int size) {
        if (size == 0) {
            if (count == 0) {
                throw new ServiceException(msg);
            }
        } else {
            if (count != size) {
                throw new ServiceException(msg);
            }
        }
    }

    private void checkData(QuDto qu) {
        if (qu == null) {
            throw new ServiceException(ApiErrorEnum.QU_CONTENT_IS_NULL);
        }
        if (StrUtil.isEmpty(qu.getContent())) {
            throw new ServiceException(ApiErrorEnum.QU_CONTENT_IS_NULL);
        }


        if (CollectionUtils.isEmpty(Collections.singletonList(qu.getQuRepoList()))) {
            throw new ServiceException(ApiErrorEnum.QU_REPO_ATLEAST_ONE);
        }

        List<QuAnswer> answers = qu.getQuAnswerList();


        if (!qu.getQuType().equals(QuTypeConstant.JDT) && CollectionUtils.isEmpty(answers)) {
            throw new ServiceException(ApiErrorEnum.QU_HAS_ANSWER);
        }


        int trueCount = 0;
        for (QuAnswer a : answers) {
            if (StrUtil.isEmpty(a.getContent())) {
                throw new ServiceException(ApiErrorEnum.QU_ANSWER_CONTEXT_IS_NULL);
            }
            if (a.getIsRight().equals(QuAnswerConstant.RIGHT)) {
                trueCount += 1;
            }
        }
        if (trueCount == 0) {
            throw new ServiceException(ApiErrorEnum.QU_ANSWER_HAS_ONE);
        }


        //单选题
        if (qu.getQuType().equals(QuTypeConstant.RADIO) && trueCount > 1) {
            throw new ServiceException(ApiErrorEnum.QU_RADIO_ANSWER_HAS_ONE);
        }

        //判断题
        if (qu.getQuType().equals(QuTypeConstant.JUDGE) && trueCount > 1) {
            throw new ServiceException(ApiErrorEnum.QU_JUDGE_ANSWER_HAS_ONE);
        }

        //多选题
        if (qu.getQuType().equals(QuTypeConstant.MULTI) && trueCount <= 1) {
            throw new ServiceException(ApiErrorEnum.QU_MULTI_ANSWER_HAS_MORE);
        }

    }
}
